/*
    Contact info:
    bhepple@freeshell.org
    http://bhepple.freeshell.org/scrmgr

    Copyright (C) 1991-2008 Bob Hepple

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/
#include <stdio.h>
#include <sys/file.h>
#include <xview/xview.h>
#include <xview/font.h>
#include <xview/notice.h>
#include <xview/panel.h>

#define SM_CLASS extern
#include "smlib.h"
#include "smio.h"
#include "smxview.h"

CHAR *smxview_rcsid(void) {
    return("$Id: smxview.c,v 1.6 2008/02/19 13:15:50 bhepple Exp $");
}

static SM_SOFTKEY 	smio_current_skey = NULL;
static Frame 		main_frame; /* Base frame for system */
static Panel		menu_panel, text_panel;
static Xv_opaque	file_menu,
			save_as_menu;
static Panel		fk_panel[8];
static f_ptr		fk_event[8];
static Panel_item	fk_upper[8], fk_lower[8];
static int		font_width, font_height;
static int		smxview_row = 0, smxview_col = 0;
static f_ptr		smio_got_a_command;
static Xv_font		default_font;
static Xv_opaque	current_fld = NULL;

#define FK_PANEL_HEIGHT 420

/*
struct window_control {
    WINDOW	*window;
    int		num_rows,
    		num_cols,
    		origin_row,
		origin_col;
};
static struct window_control wstack[SM_MAX_POPUP];
*/

static int		top_of_wstack 	= 0;
static int		cursor_valid 	= TRUE;
static int		insert_state 	= TRUE;
static int		meta_flag 	= 0;
static int 		pushed_char	= 0;
static int		pushed_command	= 0;

void f1_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('1')); }

void f2_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('2')); }

void f3_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('3')); }

void f4_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('4')); }

void f5_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('5')); }

void f6_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('6')); }

void f7_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('7')); }

void f8_event ARG2(Xv_opaque, dummy, Event *, event) 
    { if (event_is_down(event)) smio_got_a_command(SM_META('8')); }

Notify_value fk_panel_callback ARG4(Xv_window,		win,
				    Event *,		event,
				    Notify_arg,		arg,
				    Notify_event_type,	type)
{
    int 		i;
    Notify_value	retval;

    retval = notify_next_event_func(win, event, arg, type);

    if (event_is_down(event) &&
	(event_is_key_top(event) || 
	 (event_action(event) == ACTION_SELECT)))
	for (i = 0; i < 8; i++)
	    if (fk_panel[i] == win) {
		fk_event[i](win, event);
		break;
	    }
    return(retval);
}

Notify_value main_callback ARG4(Xv_window,		win,
				Event *,		event,
				Notify_arg,		arg,
				Notify_event_type,	type)
{
    Notify_value	retval = NOTIFY_IGNORED;
    int			id;


    id = event_id(event);
    if (event_is_down(event)) {
	if (event_is_key_top(event))
	    fk_event[event_id(event) - KEY_TOP(1)](win, event);
	else if (event_is_ascii(event))
	    smio_got_a_command(id);
	else if (event_is_key_right(event))
	    switch (id) {
	    case KEY_RIGHT(10): smio_got_a_command( 2); break; /* Left */
	    case KEY_RIGHT(12): smio_got_a_command( 6); break; /* Right */
	    case KEY_RIGHT( 8): smio_got_a_command(16); break; /* Up */
	    case KEY_RIGHT(14): smio_got_a_command(14); break; /* Down */
	    case KEY_RIGHT( 7): smio_got_a_command( 1); break; /* Home */
	    case KEY_RIGHT(13): smio_got_a_command( 5); break; /* End */
	    case KEY_RIGHT( 9): smio_got_a_command(SM_META('N')); break; /* PgUp */
	    case KEY_RIGHT(15): smio_got_a_command(SM_META('P')); break; /* PgDn */
	    default: break;
	    }
	else retval = notify_next_event_func(win, event, arg, type);

    } else
	retval = notify_next_event_func(win, event, arg, type);

    return(retval);
}

void save_as_event(item, op)
    Menu_item		item;
    Menu_generate	op;
{
}

/*
 * Menu handler for `file_menu (Load)'.
 */
Menu_item load_event(item, op)
    Menu_item		item;
    Menu_generate	op;
{
    switch (op) {
    case MENU_DISPLAY:
	break;
	
    case MENU_DISPLAY_DONE:
	break;
	
    case MENU_NOTIFY:
	break;
	
    case MENU_NOTIFY_DONE:
	break;
    }
    return item;
}

/*
 * Menu handler for `file_menu (Save)'.
 */
Menu_item save_event(item, op)
    Menu_item		item;
    Menu_generate	op;
{
    switch (op) {
    case MENU_DISPLAY:
	break;
	
    case MENU_DISPLAY_DONE:
	break;
	
    case MENU_NOTIFY:
	break;
	
    case MENU_NOTIFY_DONE:
	break;
    }
    return item;
}

/*
 * Menu handler for `file_menu (Clear)'.
 */
Menu_item clear_event(item, op)
    Menu_item		item;
    Menu_generate	op;
{
    switch (op) {
    case MENU_DISPLAY:
	break;
	
    case MENU_DISPLAY_DONE:
	break;
	
    case MENU_NOTIFY:
	break;
	
    case MENU_NOTIFY_DONE:
	break;
    }
    return item;
}

/*
 * Menu handler for `file_menu (Exit)'.
 */
Menu_item exit_event(item, op)
    Menu_item		item;
    Menu_generate	op;
{
    switch (op) {
    case MENU_DISPLAY:
	break;
	
    case MENU_DISPLAY_DONE:
	break;
	
    case MENU_NOTIFY:
	break;
	
    case MENU_NOTIFY_DONE:
	break;
    }
    return item;
}

void field_event(item, event)
    Panel_item	item;
    Event	*event;
{
    panel_default_handle_event(item, event);
}

void	smxview_init ARG3(int, doit, int, argc, CHAR **, argv)
{
    Xv_font		font;
    extern Menu_item	load_event();
    extern Menu_item	save_event();
    Menu_item		save_as_menu;
    int			i;

    if (doit) {
	xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);

	/* Create menus */
	save_as_menu = xv_create(XV_NULL, MENU_COMMAND_MENU,
				 /* XV_KEY_DATA, INSTANCE, ip, */
				 MENU_ITEM,
				 	/* XV_KEY_DATA, INSTANCE, ip, */
					MENU_STRING, "filename",
					MENU_GEN_PROC, save_as_event,
					NULL,
				 NULL);

	file_menu = xv_create(XV_NULL, MENU_COMMAND_MENU,
		/* XV_KEY_DATA, INSTANCE, ip, */
		MENU_TITLE_ITEM, "File",
		MENU_ITEM,
			/* XV_KEY_DATA, INSTANCE, ip, */
			MENU_STRING, "Load",
			MENU_GEN_PROC, load_event,
			NULL,
		MENU_ITEM,
			/* XV_KEY_DATA, INSTANCE, ip, */
			MENU_STRING, "Save",
			MENU_GEN_PROC, save_event,
			NULL,
		MENU_ITEM,
			/* XV_KEY_DATA, INSTANCE, ip, */
			MENU_STRING, "Save as...",
			MENU_PULLRIGHT, save_as_menu,
			NULL,
		MENU_ITEM,
			/* XV_KEY_DATA, INSTANCE, ip, */
			MENU_STRING, "Clear",
			MENU_GEN_PROC, clear_event,
			NULL,
		MENU_ITEM,
			/* XV_KEY_DATA, INSTANCE, ip, */
			MENU_STRING, "Exit",
			MENU_GEN_PROC, exit_event,
			NULL,
		MENU_DEFAULT, 2,
		NULL);

	main_frame = xv_create (NULL, FRAME,
				XV_WIDTH, 746,
				XV_HEIGHT, 478,
				XV_LABEL, argv[0],
				FRAME_SHOW_FOOTER, TRUE,
				FRAME_SHOW_RESIZE_CORNER, FALSE,
				0);
	
	/* This does not work for width with the default font. Therefore use
	   courier which does work. Fixed also has problems.
	   font_height = (int) xv_get(panel, WIN_ROW_HEIGHT) +
	   		 (int) xv_get(panel, WIN_ROW_GAP);
	   font_width  = (int) xv_get(panel, WIN_COLUMN_WIDTH) +
	   		 (int) xv_get(panel, WIN_COLUMN_GAP);
	*/
	default_font = (Xv_font) xv_get(main_frame, XV_FONT);
	
	/* Create Panels */
	menu_panel = xv_create(main_frame, PANEL,
			       XV_X, 0,
			       XV_Y, 0,
			       XV_WIDTH, WIN_EXTEND_TO_EDGE,
			       XV_HEIGHT, 37,
			       WIN_BORDER, TRUE,
			       NULL);

	notify_interpose_event_func(menu_panel,
				    (Notify_func) main_callback, 
				    NOTIFY_SAFE);
	
	xv_create(menu_panel, PANEL_BUTTON,
		  /* XV_KEY_DATA, INSTANCE, ip, */
		  XV_X, 16,
		  XV_Y, 8,
		  PANEL_LABEL_STRING, "File",
		  PANEL_ITEM_MENU, file_menu, main_frame,
		  NULL);

	text_panel = xv_create(main_frame, PANEL,
			       /* XV_KEY_DATA, INSTANCE, ip, */
			       XV_X, 0,
			       XV_Y, 47,
			       XV_WIDTH, WIN_EXTEND_TO_EDGE,
			       XV_HEIGHT, 360,
			       WIN_BORDER, TRUE,
			       NULL);
	
	notify_interpose_event_func(text_panel,
				    (Notify_func) main_callback, 
				    NOTIFY_SAFE);
	
	if ((font = (Xv_Font) xv_find(text_panel, FONT, 
				      FONT_NAME, "courier", NULL)) 
	    != NULL)
	    xv_set(text_panel, XV_FONT, font, NULL);
	
	font = (Xv_font) xv_get(text_panel, XV_FONT);
	font_width = (int) xv_get(font, FONT_DEFAULT_CHAR_WIDTH);
	font_height = (int) xv_get(font, FONT_DEFAULT_CHAR_HEIGHT);
	
	fk_event[0] = f1_event;
	fk_event[1] = f2_event;
	fk_event[2] = f3_event;
	fk_event[3] = f4_event;
	fk_event[4] = f5_event;
	fk_event[5] = f6_event;
	fk_event[6] = f7_event;
	fk_event[7] = f8_event;

	for (i = 0; i < 8; i++) {
	    fk_panel[i] = xv_create(main_frame, PANEL,
				    /* XV_KEY_DATA, INSTANCE, ip, */
				    XV_X, i * 93,
				    XV_Y, FK_PANEL_HEIGHT,
				    XV_WIDTH, 85,
				    XV_HEIGHT, 44,
				    WIN_BORDER, TRUE,
				    WIN_CONSUME_EVENTS,
				        WIN_MOUSE_BUTTONS,
				        NULL, 
				    NULL);
	    notify_interpose_event_func(fk_panel[i],
					(Notify_func) fk_panel_callback, 
					NOTIFY_SAFE);

	    fk_upper[i] = xv_create(fk_panel[i], PANEL_MESSAGE,
			    /* XV_KEY_DATA, INSTANCE, ip, */
			    XV_X, 8,
			    XV_Y, 8,
			    PANEL_LABEL_STRING, "Message",
			    PANEL_LABEL_BOLD, TRUE,
			    PANEL_EVENT_PROC, fk_event[i],
			    NULL);
	    fk_lower[i] = xv_create(fk_panel[i], PANEL_MESSAGE,
			    /* XV_KEY_DATA, INSTANCE, ip, */
			    XV_X, 8,
			    XV_Y, 24,
			    PANEL_LABEL_STRING, "Message",
			    PANEL_LABEL_BOLD, TRUE,
			    PANEL_EVENT_PROC, fk_event[i],
			    NULL);
	}

	top_of_wstack = 0;
    }
}

void	smxview_term()
{
    xv_destroy_safe(main_frame);
    /*notify_post_destroy(main_frame, DESTROY_CHECKING, NOTIFY_SAFE);
    notify_post_destroy(main_frame, DESTROY_CHECKING, NOTIFY_SAFE);*/
}

int	smxview_popup ARG4(int, num_rows, int, num_cols, int, row, int, col)
{
/*
    WINDOW	*new_window;
    int		window;

    if (top_of_wstack < (SM_MAX_POPUP - 1))
	if ((new_window = newwin(num_rows, num_cols, row, col)) != NULL) {
	    wstack[++top_of_wstack].window = new_window;
	    keypad(wstack[top_of_wstack].window, TRUE);
	    meta(wstack[top_of_wstack].window, TRUE);
	    wstack[top_of_wstack].num_rows = num_rows;
	    wstack[top_of_wstack].num_cols = num_cols;
	    wstack[top_of_wstack].origin_row = row;
	    wstack[top_of_wstack].origin_col = col;

	    if (top_of_wstack) {
		wstack[top_of_wstack].num_rows -= 2;
		wstack[top_of_wstack].num_cols -= 2;
		smio_box(top_of_wstack);
	    }
	    smio_goto(top_of_wstack, 0, 0);
	    return(top_of_wstack);
	} else
	    return(SM_ERROR);
    else
	return(SM_ERROR);
*/
}

/* Delete the popped window */
void	smxview_delwin ARG1(int, window)
{
/*
    int i;

    if (!curses_ready)
	return;

    delwin(wstack[top_of_wstack].window);
    wstack[top_of_wstack].window = NULL;
    top_of_wstack--;
    touchwin(wstack[top_of_wstack].window);
    wrefresh(wstack[top_of_wstack].window);
*/
}

void	smxview_clear ARG1(int, window)
{
    Panel_item	item;

    PANEL_EACH_ITEM(text_panel, item)
	xv_destroy(item);
    PANEL_END_EACH
}

void	smxview_clrline ARG1(int, window)
{
    Panel_item	item;
    int		row, col;

    PANEL_EACH_ITEM(text_panel, item)
	if (xv_get(item, XV_Y) / font_height == smxview_col)
	    xv_destroy(item);
    PANEL_END_EACH
}

void 	smxview_getyx ARG3(int, window, int *, row, int *, col)
{
}

void	smxview_enq ARG3(int, window, int *, row, int *, col)
{
    *row = (int) xv_get(text_panel, WIN_ROWS);
    *col = (int) xv_get(text_panel, WIN_COLUMNS);
}

void	smxview_enq_screen ARG2(int *, row, int *, col)
{
    *row = (int) xv_get(text_panel, WIN_ROWS);
    *col = (int) xv_get(text_panel, WIN_COLUMNS);
}

void	smxview_goto ARG3(int, window, int, row, int, col)
{
    smxview_row = row;
    smxview_col = col;
}

void	smxview_enh ARG2(int, window, ENH, enhancement)
{
    int	i, mapped_enh = 0;
    
    /* wattrset(wstack[window].window, mapped_enh); */
}

void	smxview_puts ARG2(int, window, CHAR *, s)
{
    int		y, x, maxlen;
    CHAR	saved;

    xv_create(text_panel, PANEL_MESSAGE,
	      XV_X, smxview_col * font_width,
	      XV_Y, smxview_row * font_height,
	      PANEL_LABEL_STRING, s,
	      PANEL_LABEL_BOLD, FALSE,
	      NULL);
}

static void meta_on()
{
/*
    wmove(fkey_window, 0, 40);
    waddstr(fkey_window, "M-");
*/
}

static void meta_off()
{
/*
    wmove(fkey_window, 0, 40);
    waddstr(fkey_window, "  ");
*/
}

static void update_insert()
{
/*
    wmove(fkey_window, 0, 36);
    if (insert_state)
	waddstr(fkey_window, "Ins");
    else
	waddstr(fkey_window, "   ");
*/
}

void smxview_paint_skey ARG3(int, i, char *, upper, char *, lower)
{
    xv_set(fk_upper[i], PANEL_LABEL_STRING, upper, NULL);
    xv_set(fk_lower[i], PANEL_LABEL_STRING, lower, NULL);
}

int	smxview_mouse ARG3(int *, row, int *, col, int *, time_delta)
{
}
	
void	smxview_refresh()
{
}

/*
 * Right trim a column
 */
int smxview_maxcol ARG2(int, window, int, col_desired)
{
    return(col_desired);
}

int smxview_insertp()
{
    return(insert_state);
}

void smxview_msg ARG1(char *, s)
{
    xv_set(main_frame, FRAME_LEFT_FOOTER, s, NULL);
}

void smxview_main_loop ARG1(f_ptr, got_a_command)
{
    smio_got_a_command = got_a_command;
    xv_main_loop(main_frame);
}

int smxview_confirm_notice ARG1(char *, s)
{
    int		result;

    result = notice_prompt(text_panel, NULL,
			   NOTICE_MESSAGE_STRINGS, s, NULL,
/*  not working ...	   NOTICE_FOCUS_XY, x, y, */
			   NOTICE_BUTTON, "Yes", 101,
			   NOTICE_BUTTON, "No",  102,
			   NOTICE_BUTTON, "Cancel", 103,
/* otherwise inherits the font of the window where it was picked - and
   if that is 'fixed', there is not enough room for the 'Yes' text ... */
			   NOTICE_FONT, default_font,
			   NULL);
    if (result == 101)
	return(SM_YES_C);
    else if (result == 102)
	return(SM_NO_C);
    else
	return(SM_CANCEL_C);
}

void smxview_error_notice ARG1(char *, s) 
{
    notice_prompt(text_panel, NULL,
		  NOTICE_MESSAGE_STRINGS, s, NULL,
		  /*  not working ...	   NOTICE_FOCUS_XY, x, y, */
		  NOTICE_BUTTON, "Ok", 101,
		  NOTICE_FONT, default_font,
		  NULL);
}

void smxview_line_error_notice ARG2(char *, msg, CHAR *, offense) 
{
    notice_prompt(text_panel, NULL,
		  NOTICE_MESSAGE_STRINGS, msg, offense, NULL,
		  /*  not working ...	   NOTICE_FOCUS_XY, x, y, */
		  NOTICE_BUTTON, "Ok", 101,
		  NOTICE_FONT, default_font,
		  NULL);
}

void smxview_beep() {}

void *smxview_create_fld ARG3(int, row, int, col, int, len)
{
    return((void *)xv_create(text_panel, PANEL_TEXT,
		     XV_X, col * font_width,
		     XV_Y, row * font_height,
		     PANEL_VALUE_DISPLAY_LENGTH, len,
		     PANEL_VALUE_STORED_LENGTH, 250,
		     PANEL_LAYOUT, PANEL_HORIZONTAL,
		     PANEL_READ_ONLY, FALSE,
		     PANEL_NOTIFY_LEVEL, PANEL_ALL,
		     PANEL_EVENT_PROC, field_event,
		     NULL));
}

void smxview_set_fld ARG2(void *, fld, char *, val)
{
    xv_set(text_panel, PANEL_CARET_ITEM, fld, NULL);
    xv_set(fld, PANEL_VALUE, val, NULL);
    current_fld = (Xv_opaque) fld;
}

/* For emacs:
 * Local Variables:
 * tab-width: 8
 * End:
 */
